import re
from PySide6.QtCore import QObject, Signal
from model.common import Common
from model.ssh_connector import SSHConnector
from model.config_reader import ConfigReader
from core import bus


class DiskPresenter(QObject):
    """磁盘监控控制器"""

    disk_check_finished = Signal(dict)  

    def __init__(self, view, server_manager):
        super().__init__()
        self.view = view
        self.server_manager = server_manager
        self.common = Common()
        self.ssh = SSHConnector()
        self.config_reader = ConfigReader()

        self.required_space_gb = float(self.config_reader.get_value("remote", "df_threshold", 50))

        self.disk_cmd = self.config_reader.get_value("remote", "df_command")

    # ---------------- 启动检测 ----------------
    def handle_disk_check(self):
        """后台线程执行磁盘检测"""
        servers = self.server_manager.get_connected_servers()
        if not servers:
            bus.log_message.emit("请先连接服务器")
            return

        def worker(server):
            return self.check_disk_space(server)

        def on_finished(results):
            # 线程池返回 list，我们转成 {ip: result}
            summary = self._build_summary(results)
            self.disk_check_finished.emit(summary)

        self.common.run_task(worker, servers, on_finished)

    # ---------------- 检查单台服务器 ----------------
    def check_disk_space(self, server: dict):
        try:
            result = self.ssh.execute_command(server, self.disk_cmd)
            if not result.get("status"):
                return self._result_dict(server, [], False, result.get("stderr") or result.get("error"))

            disks, total_info = self.parse_disk_info(result.get("stdout"))
            all_sufficient = total_info.get("is_sufficient", False)

            return self._result_dict(server, [total_info] + disks, True, None, all_sufficient)

        except Exception as e:
            return self._result_dict(server, [], False, str(e))

    # ---------------- 解析 df 输出 ----------------
    def parse_disk_info(self, output: str):
        disks = []
        lines = [l.strip() for l in output.strip().splitlines() if l.strip()]
        if len(lines) <= 1:
            return [], {}

        header, *data = lines
        *part_lines, total_line = data

        # 分区行
        for line in part_lines:
            parts = re.split(r"\s+", line)
            if len(parts) < 6:
                continue
            fs, total, used, avail, use_percent, *mount_parts = parts
            mount = " ".join(mount_parts) if mount_parts else "-"
            disks.append({
                "filesystem": fs,
                "total": total,
                "used": used,
                "avail": avail,
                "use_percent": use_percent,
                "mountpoint": mount,
                "is_total": False
            })

        # Total 行
        t_parts = re.split(r"\s+", total_line.strip()) if total_line else []
        if len(t_parts) < 5:
            return disks, {}

        fs, total, used, avail, use_percent = t_parts[:5]
        avail_gb = self._convert_to_gb(avail)
        is_sufficient = avail_gb >= self.required_space_gb

        total_info = {
            "filesystem": fs,
            "total": total,
            "used": used,
            "avail": avail,
            "use_percent": use_percent,
            "is_total": True,
            "is_sufficient": is_sufficient
        }
        return disks, total_info

    # ---------------- GB 单位转换 ----------------
    def _convert_to_gb(self, size_str: str) -> float:
        match = re.match(r"([\d.]+)([A-Za-z]*)", size_str)
        if not match:
            return 0.0
        value, unit = match.groups()
        value = float(value)
        unit = unit.upper()
        scale = {"K": 1/1024/1024, "M": 1/1024, "G": 1, "T": 1024}
        return value * scale.get(unit, 0)

    # ---------------- 汇总结果 ----------------
    def _build_summary(self, results):
        """将 list 或 dict 统一转成 {ip: {...}} 结构"""
        result_map = {}

        if isinstance(results, dict):
            # ✅ 已经是 {ip: {...}} 格式
            result_map = results
        elif isinstance(results, list):
            # ✅ 是列表格式
            result_map = {r.get("ip"): r for r in results if isinstance(r, dict) and "ip" in r}

        total = len(result_map)
        success = sum(1 for r in result_map.values() if r.get("connection_status"))
        sufficient = sum(1 for r in result_map.values() if r.get("all_sufficient"))
        failed = total - success
        insufficient = total - sufficient - failed

        stats = {
            "total_servers": total,
            "sufficient_servers": sufficient,
            "failed_servers": failed,
            "insufficient_servers": insufficient
        }

        return {"results": result_map, "statistics": stats}

    # ---------------- 单台结果 ----------------
    def _result_dict(self, server, disks, connected, error=None, all_sufficient=False):
        return {
            "station": server.get("station", "Unknown"),
            "ip": server.get("ip"),
            "disks": disks,
            "error": error,
            "all_sufficient": all_sufficient,
            "connection_status": connected
        }
